WEB-websocket,Notification通知

WEB-websocket,Notification通知

HTML5 桌面通知:Notification API

Notification API 是 HTML5 新增的桌面通知 API,用于向用户显示通知信息。该通知是脱离浏览器的,即使用户没有停留在当前标签页,甚至最小化了浏览器,该通知信息也一样会置顶显示出来。

websocket获取到数据,notify通知

用户允许网页的通知,利用websocket,将实时获取来的数据推送给用户。主要针对浏览器为chrome、火狐、safari等高级浏览器,不支持IE (ps: 本地是不行的,只有到https 的远程才可以进行推送)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// copy的 websocket 简易封装
// SimpleWebSocket
// 后期可以写个比较完善的

class SimpleWebSocket<T = any> {
private websocket: WebSocket
private isOpen: boolean
private isManualClose: boolean
private reconnectionTimer: number
private message: string[] = []

constructor(
private url: string,
private success: (data: T) => void,
private openInit?: () => void
) {
this.reset()
this.pump()
}

public send(msg: string) {
this.isOpen ? this.websocket.send(msg) : this.message.push(msg)
}

public close() {
this.isManualClose = true
this.websocket.close()
}

private reset() {
this.websocket = this.createWebSocket(this.url)
this.isOpen = false
this.isManualClose = false
this.bindEvent()
}

private createWebSocket(url: string): WebSocket {
return new WebSocket(url)
}

private bindEvent() {
this.websocket.onmessage = (data: MessageEvent) => {
this.success(data.data as T)
}
this.websocket.onopen = () => {
this.isOpen = true
this.openInit && this.openInit()
this.reconnectionTimer && window.clearInterval(this.reconnectionTimer)
}
this.websocket.onclose = () => {
if (!this.isManualClose) {
this.reconnection()
}
}
this.websocket.onerror = () => {
this.reconnection()
}
}

private pump() {
setInterval(() => {
if (this.message.length > 0) {
const msg = this.message.shift()
if (msg) { this.send(msg as string) }
}
}, 1000)
}

// 重新连接,3秒重连一次
private reconnection() {
this.reconnectionTimer && window.clearInterval(this.reconnectionTimer)
this.reconnectionTimer = window.setInterval(() => {
this.reset()
}, 3000)
}
}

export { SimpleWebSocket }
  1. 初始化websocket
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
componentDidMount() {
const config = Cookie.Get(""); // 将是否通知的布尔存到cookie中,也可以存到localstorge
if (config) {
const configValue = JSON.parse(decodeURIComponent(config));
this._data.setVoice(configValue.voice);
this._data.setNotify(configValue.notify); // boolean
}
this._websocket = new SimpleWebSocket(
Config.websocket,
data => {
const item = JSON.parse(data);
if (item.data && item.method == "") {
~~~
// 获取来的数据做处理
~~~
this._data.makeVoice();
this._data.notify(news);
this.setState({});
}
},
() => {
const token = Cookie.Get();
this._websocket.send(
JSON.stringify({
method: "subscribe",
data: {
topic: "",
client_type: "",
client_version: "1.0.0",
token: token
}
})
);
}
);
}
  1. 通知的设置

var notification = new Notification(title, options)

参数如下:

  • title:通知的标题
  • options:通知的设置选项(可选)。
    • body:通知的内容。
    • tag:代表通知的一个识别标签,相同tag时只会打开同一个通知窗口。
    • icon:要在通知中显示的图标的URL。
    • image:要在通知中显示的图像的URL。
    • data:想要和通知关联的任务类型的数据。
    • requireInteraction:通知保持有效不自动关闭,默认为false。

用户权限

想要向用户显示通知消息,需要获取用户权限,而相同的域名只需要获取一次权限。只有用户允许的权限下,Notification 才能起到作用,避免某些网站的广告滥用 Notification 或其它给用户造成影响。那么如何知道用户到底是允不允许的?

Notification.permission 该属性用于表明当前通知显示的授权状态,可能的值包括:

  • default :不知道用户的选择,默认。
  • granted :用户允许。
  • denied :用户拒绝。
1
2
3
4
5
6
7
if(Notification.permission === 'granted'){
console.log('用户允许通知');
}else if(Notification.permission === 'denied'){
console.log('用户拒绝通知');
}else{
console.log('用户还没选择,去向用户申请权限吧');
}

请求权限

当用户还没选择的时候,我们需要向用户去请求权限。Notification 对象提供了 requestPermission() 方法请求用户当前来源的权限以显示通知。

以前基于回调的语法已经弃用(当然在现在的浏览器中还是能用的),最新的规范已将此方法更新为基于 promise 的语法:

1
2
3
4
5
6
7
Notification.requestPermission().then(function(permission) {
if(permission === 'granted'){
console.log('用户允许通知');
}else if(permission === 'denied'){
console.log('用户拒绝通知');
}
});

关闭通知

1
2
3
4
5
6
7
var n = new Notification('提醒',{
body: '你的朋友圈有3条新状态,快去查看吧'
})

setTimeout(function() {
n.close();
}, 3000);

Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
public setNotify(value: boolean) {
if ((window as any).Notification) {
Notification.requestPermission(() => { // 用户允许浏览器通知
this._notify = value;
Cookie.Set( // 将是否通知的布尔存到cookie中,也可以存到localstorge
"",
JSON.stringify({
voice: this._voice,
notify: this._notify
})
);
});
}
}
// 桌面推送功能
public notify(item: NewsProfile.AsObject) {
if ((window as any).Notification && this._notify) {
var notify = new Notification("通知的标题", {
icon:
"这儿为logo图",
body: "这儿是具体的内容",
tag: 'id', // 相当于是当前通知的id,配合renotify使用,可以使多个通知不重叠
renotify : true
})

notify.onclick = function() {
window.focus();
this.close();
}
}
}
public setVoice(v: boolean) {
Cookie.Set(
"",
JSON.stringify({
voice: this._voice,
notify: this._notify
})
);
this._voice = v;
}
// 声音提示
public makeVoice() {
if (this._voice) {
const audio = document.getElementById("audioPlay"); // 一段音频文件
(audio as any).play();
}
}
  1. 是否通知的开关,包括声音的和notify的
1
2
3
4
5
6
7
8
9
10
11
<Switch
checked={this._voice}
onChange={() => {
this._voice = !this._voice;
this.props.option && this.props.option(
this._voice,
this._desk
);
this.setState({});
}}
/>

使用Service Worker发送Push推送 — web push

Web push在国外的网站还行,但在国内几乎没见到,主要还是因为谷歌在境内无法访问,因为web push走的是谷歌FCM通道,需要能接收到谷歌服务器的消息。但正常网络环境下是无法访问谷歌的,使得在国内搞它的意义不是很大,研究一下还是可以的。

PS:

不过这个浏览器通知也挺烦的,我个人比较不感冒,会把所有浏览器通知关掉。看产品需求吧。也可以用现有的库push.js.

参考链接:https://juejin.im/post/59d9b38ef265da064a0f72cc

谷歌官方 https://developers.google.com/web/fundamentals/codelabs/push-notifications/?hl=zh-cn

一个github项目 https://github.com/realtime-framework/WebPushNotifications

感谢你的打赏哦!